package site.shihuan.helpdesk.auth.service;

import cn.hutool.crypto.SecureUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import site.shihuan.helpdesk.auth.config.AuthConfiguration;
import site.shihuan.helpdesk.auth.dao.AuthUserDao;
import site.shihuan.helpdesk.auth.exception.AuthResultCode;
import site.shihuan.helpdesk.auth.model.bo.UpdateUserBO;
import site.shihuan.helpdesk.auth.model.po.AuthUserPO;
import site.shihuan.helpdesk.auth.model.vo.UserVO;
import site.shihuan.helpdesk.auth.service.AuthService;
import site.shihuan.helpdesk.auth.util.ValidateUtil;
import site.shihuan.helpdesk.security.context.UserContext;
import site.shihuan.helpdesk.common.exception.CommonException;
import site.shihuan.helpdesk.common.util.IdWorker;
import site.shihuan.helpdesk.common.manager.TokenManager;
import site.shihuan.helpdesk.common.model.JwtUser;

import java.util.HashMap;
import java.util.Map;

/**
 * 用户认证业务层
 *
 * @author 周世焕
 * @Date 2021/1/24 17:01
 */
@Service
@Slf4j
public class AuthService {

    @Autowired
    private AuthUserDao authUserDao;

    @Autowired
    private TokenManager tokenManager;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    AuthConfiguration authConfiguration;

    /**
     * 登录
     *
     * @param username
     * @param password
     * @return
     */
    public UserVO login(String username, String password) {
        UserVO userVO = authUserDao.selectByUnameAndPwd(username, SecureUtil.md5(password));
        if(userVO == null){
            throw new CommonException(AuthResultCode.UNAME_OR_PWD_WRONG);
        }
        JwtUser jwtUser = getJwtUserFromUserVO(userVO);
        String accessToken = tokenManager.createToken(jwtUser,null);
        String refreshToken = tokenManager.createToken(jwtUser,3600000L);
        userVO.setAccessToken(accessToken);
        userVO.setRefreshToken(refreshToken);
        //TODO 此处应该存储两个token到Redis
        return userVO;
    }

    /**
     * 更新用户信息
     * @param userBO
     */
    public void updateUser(UpdateUserBO userBO) {
        authUserDao.updatePeopleByTenant(userBO);
    }

    /**
     * 检查用户是否存在
     *
     * @param username  用户名
     * @return
     */
    public boolean checkUserExist(String username) {
        int count = authUserDao.countByUname(username);
        if(count > 0){
            return true;
        }
        return false;
    }

    /**
     * 获取当前用户信息
     * @return
     */
    public UserVO getUserInfo() {
        JwtUser user = UserContext.getContext().getUser();
        //用户未登录
        if(user == null) {
            return null;
        }
        return authUserDao.selectByUid(user.getUid());
    }

    /**
     * 查询用户信息
     * @param uid
     * @return
     */
    public UserVO getUserInfo(String uid) {
        return authUserDao.selectByUid(uid);
    }

    /**
     * 注册
     * @param email
     * @param password
     * @param mobile
     * @return
     */
    public AuthUserPO register(String email, String password, String mobile) {
        if(!ValidateUtil.isEmail(email)){
            throw new CommonException(AuthResultCode.EMAIL_FORMAT_INVALID);
        }
        if(!ValidateUtil.isMobile(mobile)){
            throw new CommonException(AuthResultCode.MOBILE_FORMAT_INVALID);
        }
        if(!ValidateUtil.validatePwd(password)){
            throw new CommonException(AuthResultCode.PWD_FORMAT_INVALID);
        }
        int count = authUserDao.countByEmail(email);
        if(count > 0){
            throw new CommonException(AuthResultCode.EMAIL_EXISTS);
        }
        AuthUserPO userPO = new AuthUserPO();
        userPO.setUserId(IdWorker.nextId());
        userPO.setUsername(IdWorker.nextUsername(userPO.getUserId()));
        userPO.setNickname(userPO.getUsername());
        userPO.setEmail(email);
        userPO.setMobile(mobile);
        userPO.setPassword(SecureUtil.md5(password));
        authUserDao.insertSelective(userPO);
        return userPO;
    }

    private JwtUser getJwtUserFromUserVO(UserVO userVO){
        JwtUser jwtUser = new JwtUser();
        jwtUser.setUid(userVO.getUserId());
        jwtUser.setDeptId(userVO.getDeptId());
        jwtUser.setTenantId(userVO.getTenantId());
        jwtUser.setRole(userVO.getRoles());
        return jwtUser;
    }

    /**
     * 刷新token
     * @param refreshToken
     * @return
     */
    public Map refreshToken(String refreshToken) {
        JwtUser user = tokenManager.getUserInfo(refreshToken);
        Map map = new HashMap(2);
        map.put("accessToken",tokenManager.createToken(user,null));
        map.put("refreshToken",tokenManager.createToken(user,3600000L));
        return map;
    }
}
